package service

import (
	"context"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"lot_admin_api/api"
	"lot_admin_api/internal/consts"
	"lot_admin_api/internal/dao"
	"lot_admin_api/internal/model"
	"lot_admin_api/utility/paging"
	"lot_admin_api/utility/response"
)

type sDepartment struct{}

var (
	insDepartment = sDepartment{}
)

func Department() *sDepartment {
	return &insDepartment
}

// AddDepartment 添加部门
func (s *sDepartment) AddDepartment(ctx context.Context, req *model.DepartmentInfoReq) (lastInsertId int64, err error) {
	r := g.RequestFromCtx(ctx)
	Company().searchCompany(ctx, req.CompanyId)
	// 保存
	saveInfo, err := dao.LotDepartment.Ctx(ctx).OmitEmpty().Save(&req)
	if err != nil {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "保存部门失败")
	}
	lastInsertId, err = saveInfo.LastInsertId()
	return lastInsertId, err
}

// EditDepartment 编辑部门 返回当前部门id
func (s *sDepartment) EditDepartment(ctx context.Context, req *api.EditDepartmentReq) (lastInsertId int64, err error) {
	r := g.RequestFromCtx(ctx)
	if _, err = dao.LotDepartment.Ctx(ctx).OmitEmpty().Where("id", req.Id).Update(&req); err != nil {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "编辑部门失败")
	}
	return req.Id, err
}

// DeleteDepartment 删除部门 返回当前部门id
func (s *sDepartment) DeleteDepartment(ctx context.Context, req *api.DeleteDepartmentReq) (lastInsertId int64, err error) {
	_, searchInfo := s.SearchDepartment(ctx, req.Id) // 获取搜索条件 ,查询是否有当前部门
	// 查询当前部门下是否有其他的子部门,如果有的话不能删除
	searchChildInfo := g.Map{
		"parent_id":  searchInfo.Id,
		"company_id": searchInfo.CompanyId,
	}
	r := g.RequestFromCtx(ctx)
	// 判断该部门下是否有子部门
	if searchChildList, _ := dao.LotDepartment.Ctx(ctx).Where(&searchChildInfo).All(); searchChildList.Len() != 0 {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "该部门有"+gconv.String(searchChildList.Len())+"个子部门,不能删除")
	}
	// 判断该门店下是否有员工
	if searchStaff, _ := dao.LotStaff.Ctx(ctx).Where(g.Map{"department_id": searchInfo.Id}).All(); searchStaff.Len() != 0 {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "该部门有"+gconv.String(searchStaff.Len())+"个员工,不能删除")
	}
	// 做个判断查询当前
	_, err = dao.LotDepartment.Ctx(ctx).Where("id", req.Id).Delete()
	return req.Id, err
}

// BranchDeleteDepartment 批量删除部门 返回删除部门id/ 未写该功能
func (s *sDepartment) BranchDeleteDepartment(ctx context.Context, req *api.BatchDeleteDepartmentReq) (res *model.BranchDepartmentIdRes, err error) {

	return res, err
}

// DepartmentInfo 获取部门详情 返回当前部门id
func (s *sDepartment) DepartmentInfo(ctx context.Context, req *api.GetDepartmentReq) (res *api.DepartmentInfoRes, err error) {
	searchInfo, _ := s.SearchDepartment(ctx, req.Id) // 获取搜索条件 ,查询是否有当前部门
	err = dao.LotDepartment.Ctx(ctx).Where(searchInfo).Scan(&res)
	return res, err
}

// DepartmentList  获取部门数组
func (s *sDepartment) DepartmentList(ctx context.Context, req *model.DepartmentListReq) (res *model.DepartmentListRes, err error) {
	findList := make([]*model.DepartmentInfoRes, 0)
	searchInfo := g.Map{
		"company_id":           req.CompanyId,
		"department_name like": "%" + req.DepartmentName + "%",
	}
	// 获取分页偏移量
	startNum, endNum := paging.Paging(req.Paging)
	_ = dao.LotDepartment.Ctx(ctx).OmitEmpty().Where(searchInfo).Limit(startNum, endNum).Scan(&findList)
	// 获取总条数
	countNum, err := dao.LotDepartment.Ctx(ctx).OmitEmpty().Where(searchInfo).Count()
	// 获取总页码
	PutPageList := paging.PutCount(req.Paging, countNum)
	res = &model.DepartmentListRes{
		List:    findList,
		PutPage: *PutPageList,
	}
	return res, err
}

// DepartmentTree 获取部门树结构详情
func (s *sDepartment) DepartmentTree(ctx context.Context, req *model.DepartmentTreeRes) (findOne *model.DepartmentTreeInfoRes, err error) {
	var tree []model.DepartmentTreeInfoRes
	if req.Id == 0 {
		_ = dao.LotDepartment.Ctx(ctx).Where(g.Map{"parent_id": 0}).Scan(&findOne) // 当没传id时 获取最顶层级
	} else {
		_, findOne = s.SearchDepartment(ctx, req.CompanyId)
	}
	// 部门的递归查询sql
	searchSql := `
				WITH RECURSIVE tree_cte as
				(
    				select * from lot_department where parent_id = ?
    				UNION ALL
					select t.* from lot_department t inner join tree_cte tcte on t.parent_id = tcte.id
				)
				SELECT id,department_name,parent_id,department_remark FROM tree_cte WHERE deleted_at IS NULL AND company_id = ?;
			`
	// 通过原生sql 查询数组
	searchInfo, err := g.DB().GetAll(ctx, searchSql, g.Slice{req.Id, req.CompanyId})
	// 请求获得参数装换 tree 格式
	_ = gconv.Scan(searchInfo, &tree)
	//将一维数组转换为递归数组
	tree = s.CreateTree(tree, findOne.Id)
	findOne.Children = tree
	return findOne, err
}

// SearchDepartment 查询当前部门是否存在 返回查询条件和当前部门的详情
func (s *sDepartment) SearchDepartment(ctx context.Context, id int64) (res *model.DepartmentSearchInfo, findOne *model.DepartmentTreeInfoRes) {
	r := g.RequestFromCtx(ctx)
	_ = dao.LotDepartment.Ctx(ctx).Where("id", id).Scan(&findOne)
	if findOne == nil {
		response.JsonExit(r, consts.HTTPInternalServer.Code(), "没有该部门")
	}
	return res, findOne
}

// CreateTree  查询部门tree创建树状结构  nodes 一维树结构  ParentId第一层的对比的父级id
func (s *sDepartment) CreateTree(nodes []model.DepartmentTreeInfoRes, ParentId int64) []model.DepartmentTreeInfoRes {
	tree := make([]model.DepartmentTreeInfoRes, 0)
	var roots, children []model.DepartmentTreeInfoRes
	for _, v := range nodes {
		if v.ParentId == ParentId {
			roots = append(roots, v)
		} else {
			children = append(children, v)
		}
	}
	for _, v := range roots {
		rootNode := &model.DepartmentTreeInfoRes{
			Id:               v.Id,
			ParentId:         v.ParentId,
			DepartmentName:   v.DepartmentName,
			DepartmentRemark: v.DepartmentRemark,
		}
		s.Recursion(rootNode, children)
		tree = append(tree, *rootNode)
	}
	return tree
}

// Recursion  递归处理部门tree
func (s *sDepartment) Recursion(rootNode *model.DepartmentTreeInfoRes, children []model.DepartmentTreeInfoRes) {
	id := rootNode.Id
	for _, v := range children {
		if id == v.ParentId {
			childNode := &model.DepartmentTreeInfoRes{
				Id:               v.Id,
				ParentId:         v.ParentId,
				DepartmentName:   v.DepartmentName,
				DepartmentRemark: v.DepartmentRemark,
			}
			s.Recursion(childNode, children)
			rootNode.Children = append(rootNode.Children, *childNode)
		}

	}
}
